package com.android.basiclib.utils

import android.util.Base64
import com.android.basiclib.utils.log.MyLogUtils
import java.io.ByteArrayOutputStream
import java.security.InvalidKeyException
import java.security.KeyFactory
import java.security.NoSuchAlgorithmException
import java.security.interfaces.RSAPublicKey
import java.security.spec.InvalidKeySpecException
import java.security.spec.X509EncodedKeySpec
import javax.crypto.BadPaddingException
import javax.crypto.Cipher
import javax.crypto.IllegalBlockSizeException
import javax.crypto.NoSuchPaddingException

/**
 * @auther Newki
 * @date 2023/3/6
 * @description RSA加密工具类
 */
object RSAUtils {

    /**
     * RSA的加密
     *
     * @param str       需要加密的原始字符串
     * @return 加密之后的文本
     */
    @JvmStatic
    fun rsaEncode(str: String): String? {

        val publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDSekMVMaO4eo0XpWTJpNlacErW" +
                "iS7JqZ3AMO2i+BtuIaA+fRRwZljeiCmysIr7B7u9UnJIswATTlM7PFVaxN3gk0k0" +
                "6MgjuP0SIaHtDH8WaAKYstvoujbYidtaDagq1LeY39OmJUxcKp5ofPuSknBJ+K94" +
                "MRoIS1MKe3IWJBhc3QIDAQAB"

        var outStr = ""

        try {
            val MAX_ENCRYPT_BLOCK = 64 //分段加密
            val data = str.toByteArray(charset("UTF-8"))  //待加密的数据

            //初始化Cipher的RSA加密对象
            val decoded = Base64.decode(publicKey, Base64.DEFAULT)
            val pubKey = KeyFactory.getInstance("RSA").generatePublic(X509EncodedKeySpec(decoded)) as RSAPublicKey
            // RSA加密
            val cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding")
            cipher.init(Cipher.ENCRYPT_MODE, pubKey)


            //分段加密临时变量
            val inputLen = data.size
            val out = ByteArrayOutputStream()
            var offSet = 0
            var cache: ByteArray
            var i = 0

            //开始对数据分段加密
            while (inputLen - offSet > 0) {
                cache = if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
                    cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK)
                } else {
                    cipher.doFinal(data, offSet, inputLen - offSet)
                }
                out.write(cache, 0, cache.size)
                i++
                offSet = i * MAX_ENCRYPT_BLOCK
            }
            val encryptedData = out.toByteArray()
            out.close()

            outStr = Base64.encodeToString(encryptedData, Base64.DEFAULT)

            return outStr

        } catch (e: NoSuchAlgorithmException) {
            MyLogUtils.e("无此算法")
            e.printStackTrace()
        } catch (e: InvalidKeySpecException) {
            MyLogUtils.e("公钥非法")
            e.printStackTrace()
        } catch (e: NullPointerException) {
            MyLogUtils.e("公钥数据为空")
            e.printStackTrace()
        } catch (e: NoSuchPaddingException) {
            MyLogUtils.e("明文数据已损坏")
            e.printStackTrace()
        } catch (e: IllegalBlockSizeException) {
            MyLogUtils.e("明文长度非法")
            e.printStackTrace()
        } catch (e: InvalidKeyException) {
            MyLogUtils.e("加密公钥非法,请检查")
            e.printStackTrace()
        } catch (e: BadPaddingException) {
            e.printStackTrace()
        } catch (e: Exception) {
            e.printStackTrace()
        }
        MyLogUtils.w("rsaToken 加密失败的值:$outStr")
        return outStr
    }

}